Imports System.Data
Imports System.Data.SqlClient
Imports System.Text

'***********************************************************************************************************
'
'      Application:  SQL Server Cache Manager
'       Written By:  Blake Pell (bpell@indiana.edu, blakepell@hotmail.com)
'          Website:  http://www.blakepell.com
'             Blog:  http://www.blakepell.com/Main/Blog.aspx
'                    http://blakepell.spaces.live.com
'  Additional Info:  SQL to query the execution cache was originally derivied from a blog post by
'                    Glenn Berry located at:
'
'                    http://glennberrysqlperformance.spaces.live.com/blog/cns!45041418ECCAA960!366.entry
'
'          License:  Check this projects site location on Code Plex for the license information.  This 
'                    CodePlex project is located at:
'
'                    http://www.codeplex.com/sqlservercache
'
'***********************************************************************************************************

Public Class Main

    ''' <summary>
    ''' Encryption key used for saving the data to the text file.
    ''' </summary>
    ''' <remarks></remarks>
    Private _encryptionKey As String = "08F31FE7-F17B-4026-8F19-89EB22C34CF3"

    ''' <summary>
    ''' Whether or not the program should save the last used connection information.
    ''' </summary>
    ''' <remarks></remarks>
    Private _saveConnectionInformation As Boolean = True

    ''' <summary>
    ''' The last query run
    ''' </summary>
    ''' <remarks></remarks>
    Private _sql As String = ""

    ''' <summary>
    ''' Code that executes when the main form is first loaded.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub Main_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        lstObjectType.SetItemChecked(0, True)
        lstObjectType.SetItemChecked(1, True)
        Call LoadConnectionInfo()
        SetStatus("Idle")
    End Sub

    ''' <summary>
    ''' Executes the cache query based off of the given criteria.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks>Code was placed in the menu item because of it's shortcut key support</remarks>
    Private Sub RunQueryToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RunQueryToolStripMenuItem.Click
        Call ExecuteQuery(GetSql, False)
    End Sub

    ''' <summary>
    ''' Makes a call to the code in the menu item that runs the query.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub ToolStripButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton1.Click
        Call RunQueryToolStripMenuItem_Click(Nothing, Nothing)
    End Sub

    ''' <summary>
    ''' Disables the controls that allow you to execute a query.
    ''' </summary>
    ''' <remarks>For use while a query is currently running.</remarks>
    Private Sub DisableExecuteControls()
        ToolStripButton1.Enabled = False
        RunQueryToolStripMenuItem.Enabled = False
        Application.DoEvents()
    End Sub

    ''' <summary>
    ''' Enables the controls that allow you to execute a query.
    ''' </summary>
    ''' <remarks>For use to re-enable after a query has completed.</remarks>
    Private Sub EnableExecuteControls()
        ToolStripButton1.Enabled = True
        RunQueryToolStripMenuItem.Enabled = True
        Application.DoEvents()
    End Sub

    ''' <summary>
    ''' Builds a connection string for our use based on the given criteria on the form.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ConnectionString() As String
        Dim Sb As New StringBuilder

        If txtPort.Text = "" Then
            Sb.AppendFormat("server={0};", txtServer.Text)
        Else
            Sb.AppendFormat("server={0},{1};", txtServer.Text, txtPort.Text)
        End If

        If chkTrustedConnection.Checked = True Then
            Sb.AppendFormat("Trusted_Connection=Yes;")
        Else
            Sb.AppendFormat("Uid={0};Pwd={1};", txtUsername.Text, txtPassword.Text)
        End If

        Return Sb.ToString

    End Function

    ''' <summary>
    ''' Loads the text from a given cell into a text editor window.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub DataGridView1_CellClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellClick
        ' -1 represents the sorting column row
        If e.RowIndex <> -1 Then
            txtEditor.Text = DataGridView1.SelectedCells.Item(0).Value
            TabControl1.TabPages(1).Text = "Data From Grid Cell"
            TabControl1.SelectTab(1)
        End If

    End Sub

    ''' <summary>
    ''' Exits the program.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub ExitToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExitToolStripMenuItem.Click
        End
    End Sub

    ''' <summary>
    ''' Saves the connection information out to our INI settings file.
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub SaveConnectionInfo()

        Dim oFile As New Argus.Utilities.INI(Application.StartupPath & "\ConnectionInfo.ini")

        If _saveConnectionInformation = True Then
            oFile.WriteToINI("ConnectionInfo", "Server", Argus.Cryptography.StringEncryption.Encrypt(txtServer.Text, _encryptionKey))
            oFile.WriteToINI("ConnectionInfo", "Port", Argus.Cryptography.StringEncryption.Encrypt(txtPort.Text, _encryptionKey))
            oFile.WriteToINI("ConnectionInfo", "Username", Argus.Cryptography.StringEncryption.Encrypt(txtUsername.Text, _encryptionKey))
            oFile.WriteToINI("ConnectionInfo", "Password", Argus.Cryptography.StringEncryption.Encrypt(txtPassword.Text, _encryptionKey))
            oFile.WriteToINI("ConnectionInfo", "TrustedConnection", Argus.Cryptography.StringEncryption.Encrypt(chkTrustedConnection.Checked.ToString.ToLower, _encryptionKey))
            oFile.WriteToINI("ConnectionInfo", "SaveConnectionInformation", Argus.Cryptography.StringEncryption.Encrypt(_saveConnectionInformation.ToString, _encryptionKey))
        Else
            oFile.WriteToINI("ConnectionInfo", "Server", "")
            oFile.WriteToINI("ConnectionInfo", "Port", "")
            oFile.WriteToINI("ConnectionInfo", "Username", "")
            oFile.WriteToINI("ConnectionInfo", "Password", "")
            oFile.WriteToINI("ConnectionInfo", "TrustedConnection", "")
            oFile.WriteToINI("ConnectionInfo", "SaveConnectionInformation", Argus.Cryptography.StringEncryption.Encrypt("False", _encryptionKey))
        End If

    End Sub

    ''' <summary>
    ''' Loads the saved connection information out from our INI file.
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub LoadConnectionInfo()

        If System.IO.File.Exists(Application.StartupPath & "\ConnectionInfo.ini") = False Then
            Exit Sub
        End If

        Dim Buf As String = ""
        Dim oFile As New Argus.Utilities.INI(Application.StartupPath & "\ConnectionInfo.ini")

        txtServer.Text = Argus.Cryptography.StringEncryption.Decrypt(oFile.GetFromINI("ConnectionInfo", "Server"), _encryptionKey)
        txtPort.Text = Argus.Cryptography.StringEncryption.Decrypt(oFile.GetFromINI("ConnectionInfo", "Port"), _encryptionKey)
        txtUsername.Text = Argus.Cryptography.StringEncryption.Decrypt(oFile.GetFromINI("ConnectionInfo", "Username"), _encryptionKey)
        txtPassword.Text = Argus.Cryptography.StringEncryption.Decrypt(oFile.GetFromINI("ConnectionInfo", "Password"), _encryptionKey)

        Buf = Argus.Cryptography.StringEncryption.Decrypt(oFile.GetFromINI("ConnectionInfo", "SaveConnectionInformation"), _encryptionKey)

        If Buf = "" Or Buf.ToLower = "true" Then
            _saveConnectionInformation = True
        Else
            _saveConnectionInformation = False
        End If

        If Argus.Cryptography.StringEncryption.Decrypt(oFile.GetFromINI("ConnectionInfo", "TrustedConnection"), _encryptionKey) = "true" Then
            chkTrustedConnection.Checked = True
            SaveConnectionInformationToolStripMenuItem.Checked = True
        Else
            chkTrustedConnection.Checked = False
            SaveConnectionInformationToolStripMenuItem.Checked = False
        End If

        oFile = Nothing

    End Sub

    ''' <summary>
    ''' Shows the about form.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub AboutToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AboutToolStripMenuItem.Click
        Dim AboutBox1 As New About
        AboutBox1.ShowDialog()
    End Sub

    ''' <summary>
    ''' Calls the code sub that saves the data grid.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub ToolStripButton2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton2.Click
        Call SaveGridDataToolStripMenuItem_Click(Nothing, Nothing)
        Me.BringToFront() : Me.Focus()
    End Sub

    ''' <summary>
    ''' Saves the contents of the data grid out to a file.  It will load a form that will allow them the choice to save in tab delimited format or XML format.
    ''' XML format is the default.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks>We put the code in the menu item for it's shortcut key support</remarks>
    Private Sub SaveGridDataToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveGridDataToolStripMenuItem.Click

        If DataGridView1.DataSource Is Nothing Then
            MessageBox.Show("The data grid has no data to save", "No Data", MessageBoxButtons.OK, MessageBoxIcon.Information)
            Exit Sub
        End If

        Dim FormSave As New SaveDialog()
        FormSave.ShowDialog()

        If FormSave.rdoTab.Checked = False And FormSave.rdoXml.Checked = False Then
            Exit Sub        
        End If

        Dim Sb As New StringBuilder
        SaveFileDialog1.OverwritePrompt = True
        SaveFileDialog1.SupportMultiDottedExtensions = True
        SaveFileDialog1.Title = "Save Data Grid"
        SaveFileDialog1.FileName = ""

        If FormSave.rdoXml.Checked = True Then
            SaveFileDialog1.Filter = "*.xml|*.xml|*.*|*.*"
        ElseIf FormSave.rdoTab.Checked = True Then
            SaveFileDialog1.Filter = "*.txt|*.txt|*.*|*.*"
        End If

        SaveFileDialog1.ShowDialog()

        If SaveFileDialog1.FileName = "" Then Exit Sub

        If FormSave.rdoXml.Checked = True Then
            SetStatus("Saving")
            Dim Dt As DataTable = DirectCast(DataGridView1.DataSource, DataSet).Tables(0)

            Try
                Call DisableExecuteControls()
                Dt.WriteXml(SaveFileDialog1.FileName)
                SetStatus("Save Complete")
            Catch ex As Exception
                MessageBox.Show(ex.Message, "An error has occured", MessageBoxButtons.OK, MessageBoxIcon.Error)
                SetStatus("Error Saving")
            Finally
                Call EnableExecuteControls()
            End Try

        ElseIf FormSave.rdoTab.Checked = True Then
            SetStatus("Creating tab delimiated text")

            For Each Row As DataGridViewRow In DataGridView1.Rows
                For Each Cell As DataGridViewCell In Row.Cells
                    Sb.AppendFormat("{0}{1}", Cell.Value.ToString, vbTab)
                Next
                Sb = New StringBuilder(Sb.ToString.Trim(vbTab))
                Sb.Append(vbCrLf)
            Next

            SetStatus("Saving...")

            Try
                Call DisableExecuteControls()
                My.Computer.FileSystem.WriteAllText(SaveFileDialog1.FileName, Sb.ToString, False, System.Text.Encoding.ASCII)
                SetStatus("Save Complete")
            Catch ex As Exception
                MessageBox.Show(ex.Message, "An error has occured", MessageBoxButtons.OK, MessageBoxIcon.Error)
                SetStatus("Error Saving")
            Finally
                Call EnableExecuteControls()
            End Try

        End If

        FormSave.Close() : FormSave.Dispose()
        Me.BringToFront() : Me.Focus()

    End Sub

    ''' <summary>
    ''' Displays the form that gives options to clear the cache.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub ClearCacheToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ClearCacheToolStripMenuItem.Click

        If IsConnectionSetup() = False Then
            MsgBox("You must set your connection information before this dialog can be opened.")
            txtServer.Focus()
            Exit Sub
        End If

        Dim NewForm As New ClearPlanCache(ConnectionString)
        NewForm.ShowDialog()

    End Sub

    ''' <summary>
    ''' Code for when the form resizes.  This is used to resize the height of the data grid.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub Main_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
        TabControl1.Height = Me.Height - 340
        TabControl1.Width = Me.Width - 40
        'DataGridView1.Height = Me.Height - 330
    End Sub

    ''' <summary>
    ''' Changes the options that are available when the trusted connection check box is toggled.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub chkTrustedConnection_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkTrustedConnection.CheckedChanged
        txtUsername.Text = ""
        txtPassword.Text = ""

        If chkTrustedConnection.Checked = True Then
            txtUsername.Enabled = False
            txtPassword.Enabled = False
        Else
            txtUsername.Enabled = True
            txtPassword.Enabled = True
        End If

    End Sub

    ''' <summary>
    ''' Determins whether the connection information is setup properly or not.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function IsConnectionSetup() As Boolean

        If txtServer.Text = "" Then
            Return False
        ElseIf txtUsername.Text = "" And chkTrustedConnection.Checked = False Then
            Return False
        Else
            Return True
        End If

    End Function

    ''' <summary>
    ''' Returns the Sql Statement to Execute.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks>This needs to be turned into a parameterized query.</remarks>
    Private Function GetSql() As String

        Dim Sb As New StringBuilder
        Dim SqlTemp As New StringBuilder

        Sb.AppendFormat("SELECT TOP {0} usecounts, size_in_bytes, cacheobjtype, objtype, text ", txtRecordsToReturn.Text)
        Sb.AppendLine("FROM sys.dm_Exec_cached_plans ")
        Sb.AppendLine("CROSS APPLY sys.dm_exec_sql_text(plan_handle) ")
        Sb.AppendLine("WHERE cacheobjtype = 'Compiled Plan' ")

        For Each Item As String In lstObjectType.CheckedItems
            SqlTemp.AppendFormat("'{0}',", Item)
        Next

        If SqlTemp.ToString <> "" Then
            Sb.AppendFormat("AND objtype In ({0}) ", SqlTemp.ToString.Trim(","))
        End If

        If txtSqlContains.Text <> "" Then
            Sb.AppendFormat("AND [text] Like '%{0}%'", txtSqlContains.Text)
        End If

        Sb.AppendFormat("AND usecounts {0} {1} ", ddUseCountOperator.Text, txtUseCount.Text)
        Sb.AppendFormat("AND size_in_bytes {0} {1} ", ddSizeInBytesOperator.Text, txtSizeInBytes.Text)
        Sb.AppendFormat("ORDER BY {0} {1} ", ddOrderBy.Text, ddOrderByDirection.Text)

        Return Sb.ToString

    End Function

    ''' <summary>
    ''' Shows the SQL that will run to get the cache in the SQL editor window.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub ViewSQLForCurrentQueryInEditorToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ViewSQLForCurrentQueryInEditorToolStripMenuItem.Click

        If _sql = "" Then
            MessageBox.Show("No SQL for the last query run is available.  This may indicate that you have not run a query yet.", "No SQL", MessageBoxButtons.OK, MessageBoxIcon.Information)
            Exit Sub
        End If

        txtEditor.Text = _sql
        TabControl1.TabPages(1).Text = "Last SQL Run"
        TabControl1.SelectTab(1)
    End Sub

    ''' <summary>
    ''' Saves the connection information.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub SaveConnectionInformationToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveConnectionInformationToolStripMenuItem.Click
        _saveConnectionInformation = Not _saveConnectionInformation
        SaveConnectionInformationToolStripMenuItem.Checked = _saveConnectionInformation
        Call SaveConnectionInfo()
    End Sub

    ''' <summary>
    ''' Opens an a saved XML file and loads it into the data grid.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub OpenXMLSaveFileToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OpenXMLSaveFileToolStripMenuItem.Click

        OpenFileDialog1.SupportMultiDottedExtensions = True
        OpenFileDialog1.Title = "Open Xml File"
        OpenFileDialog1.FileName = ""
        OpenFileDialog1.Filter = "*.xml|*.xml|*.*|*.*"
        OpenFileDialog1.ShowDialog()

        If OpenFileDialog1.FileName = "" Then
            Exit Sub
        Else
            ' Create the data table's schema, if we add more fields to the results this will have to be updated.
            Dim Dt As New DataTable("Table")
            Dt.Columns.Add("usecounts")
            Dt.Columns.Add("size_in_bytes")
            Dt.Columns.Add("cacheobjtype")
            Dt.Columns.Add("objtype")
            Dt.Columns.Add("text")

            Try
                Dt.ReadXml(OpenFileDialog1.FileName)
                DataGridView1.DataSource = Dt
            Catch ex As Exception
                MessageBox.Show("An error has occured:  " & ex.Message, "An error has occured", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Finally
                Dt.Dispose()
            End Try

        End If

    End Sub

    ''' <summary>
    ''' Routing tool bar menu option to the menu item sub with shortcut key support.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub OpenXmlFile_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OpenXmlFile.Click
        Call OpenXMLSaveFileToolStripMenuItem_Click(Nothing, Nothing)
    End Sub

    ''' <summary>
    ''' Displays the data cache allocation from sys.dm_os_memory_cache_counters 
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub DisplayCacheAllocationToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DisplayCacheAllocationToolStripMenuItem.Click

        Dim SqlSb As New StringBuilder
        SqlSb.AppendLine("SELECT [name] as [name], ")
        SqlSb.AppendLine("		 [type] as [type], ")
        SqlSb.AppendLine("       [single_pages_kb] + [multi_pages_kb] AS cache_kb, ")
        SqlSb.AppendLine("       [entries_count] ")
        SqlSb.AppendLine("       FROM sys.dm_os_memory_cache_counters ")
        SqlSb.AppendLine("       ORDER BY single_pages_kb + multi_pages_kb DESC ")

        Call ExecuteQuery(SqlSb.ToString, True)

    End Sub

    ''' <summary>
    ''' Call to the menu sub for this toolbar item.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub ToolStripButton3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton3.Click
        Call DisplayCacheAllocationToolStripMenuItem_Click(Nothing, Nothing)
    End Sub

    ''' <summary>
    ''' Auto resizes rows and columns in the data grid at the users request.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub ToolStripButton4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton4.Click
        Call AutoResizeRowsAndColumnsToolStripMenuItem_Click(Nothing, Nothing)
    End Sub

    ''' <summary>
    ''' Auto resizes rows and columns in the data grid at the users request.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub AutoResizeRowsAndColumnsToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AutoResizeRowsAndColumnsToolStripMenuItem.Click
        DataGridView1.AutoResizeColumns()
        DataGridView1.AutoResizeRows()
    End Sub

    ''' <summary>
    ''' Sets the status on the grid and then calls an Application.DoEvents to make sure the UI updates.
    ''' </summary>
    ''' <remarks></remarks>
    Sub SetStatus(ByVal StatusMessage As String)
        lblStatus.Text = String.Format("Status:  {0}", StatusMessage)
        Application.DoEvents()
    End Sub

    ''' <summary>
    ''' Copies all of the text in the grid in tab delimited format.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub CopyAllTextInDataGridToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CopyAllTextInDataGridToolStripMenuItem.Click

        Try
            Call DisableExecuteControls()

            SetStatus("Creating tab delimiated text")

            Dim Sb As New StringBuilder

            For Each Row As DataGridViewRow In DataGridView1.Rows
                For Each Cell As DataGridViewCell In Row.Cells
                    Sb.AppendFormat("{0}{1}", Cell.Value.ToString, vbTab)
                Next
                Sb = New StringBuilder(Sb.ToString.Trim(vbTab))
                Sb.Append(vbCrLf)
            Next

            SetStatus("Putting the text on the clipboard")
            Clipboard.SetText(Sb.ToString)
            SetStatus("Copy Complete")
        Catch ex As Exception
            MessageBox.Show(ex.Message, "An error has occured", MessageBoxButtons.OK, MessageBoxIcon.Error)
        Finally
            Call EnableExecuteControls()
        End Try

    End Sub

    ''' <summary>
    ''' Displays the results of the performance counter query for all and filtered by cache.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub PerformanceCountersToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PerformanceCountersToolStripMenuItem.Click

        Dim DialogPerformance As New DialogPerformanceCounter
        DialogPerformance.ShowDialog()

        If DialogPerformance.DialogResult = Windows.Forms.DialogResult.Cancel Or (DialogPerformance.rdoAll.Checked = False And DialogPerformance.rdoCache.Checked = False) Then
            DialogPerformance.Dispose()
            Me.Focus()
            Exit Sub
        End If

        Dim SqlSb As New StringBuilder
        SqlSb.AppendLine("SELECT [counter_name], [object_name], [instance_name], [cntr_value] ")
        SqlSb.AppendLine("FROM master..sysperfinfo ")

        ' Add a where clause if the user wants to filter by the cache entries
        If DialogPerformance.rdoCache.Checked = True Then
            SqlSb.AppendLine("WHERE counter_name Like '%cache%' ")
        End If

        SqlSb.AppendLine("ORDER BY [counter_name] ")

        Call ExecuteQuery(SqlSb.ToString, False)

        DialogPerformance.Close()
        DialogPerformance.Dispose()
        Me.BringToFront() : Me.Focus()

    End Sub

    ''' <summary>
    ''' Executes a query and puts the results into the data grid view.
    ''' </summary>
    ''' <param name="Sql"></param>
    ''' <remarks></remarks>
    Sub ExecuteQuery(ByVal Sql As String, ByVal AutoResizeGrid As Boolean)

        If IsConnectionSetup() = False Then
            MsgBox("You must set your connection information before the server can be queried.")
            txtServer.Focus()
            Exit Sub
        End If

        Call DisableExecuteControls()
        Call SaveConnectionInfo()

        lblStatus.Text = "Status: Creating Query"
        Application.DoEvents()

        lblStatus.Text = "Status: Connecting"
        Application.DoEvents()

        Dim Conn As New SqlConnection(ConnectionString)

        Try
            Conn.Open()
        Catch ex As Exception
            MsgBox(ex.Message)
            Conn.Close() : Conn.Dispose() : Conn = Nothing
            Call EnableExecuteControls()
            lblStatus.Text = "Status: Idle"
            Exit Sub
        End Try

        lblStatus.Text = "Status: Getting Data"
        Application.DoEvents()

        ' Save the text of this query in the last query run variable for display later if the user wants to see it
        _sql = Sql
        txtEditor.Text = _sql

        Dim Da As New SqlDataAdapter(Sql, Conn)
        Dim Ds As New DataSet

        Try
            Da.Fill(Ds)
        Catch ex As Exception
            MsgBox(ex.Message)
            Ds.Dispose() : Ds = Nothing
            Da.Dispose() : Da = Nothing
            Conn.Close() : Conn.Dispose() : Conn = Nothing
            Call EnableExecuteControls()
            lblStatus.Text = "Status: Idle"
            Exit Sub
        End Try

        DataGridView1.DataSource = Ds
        DataGridView1.DataMember = Ds.Tables(0).TableName

        If AutoResizeGrid = True Then
            DataGridView1.AutoResizeColumns()
        End If

        Call EnableExecuteControls()
        lblStatus.Text = "Status: Idle"
        Application.DoEvents()

        ' Object cleanup
        Ds.Dispose() : Ds = Nothing
        Da.Dispose() : Da = Nothing
        Conn.Close() : Conn.Dispose() : Conn = Nothing

    End Sub

    ''' <summary>
    ''' Pointer to the menu option for performance counters
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks>Have to run the bring to front here again because of being called from the toolbar.</remarks>
    Private Sub ToolStripButton5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton5.Click
        Call PerformanceCountersToolStripMenuItem_Click(Nothing, Nothing)
        Me.BringToFront() : Me.Focus()
    End Sub

    ''' <summary>
    ''' Opens the project site in the default web browser.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub CodePlexProjectSiteToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CodePlexProjectSiteToolStripMenuItem.Click
        Call StartUrl("http://www.codeplex.com/sqlservercache")
    End Sub

    ''' <summary>
    ''' Opens the RSS feed for all project updates
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub AllProjectUpdatesToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AllProjectUpdatesToolStripMenuItem.Click
        Call StartUrl("http://www.codeplex.com/sqlservercache/Project/ProjectRss.aspx")
    End Sub

    ''' <summary>
    ''' Opens the RSS feed for all releases
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub AllReleasesToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AllReleasesToolStripMenuItem.Click
        Call StartUrl("http://www.codeplex.com/sqlservercache/Project/ProjectRss.aspx?ProjectRSSFeed=codeplex%3a%2f%2frelease%2fsqlservercache")
    End Sub

    ''' <summary>
    ''' Opens the RSS feed for all source code updates
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub AllSourceCodeUpdatesToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AllSourceCodeUpdatesToolStripMenuItem.Click
        Call StartUrl("http://www.codeplex.com/sqlservercache/Project/ProjectRss.aspx?ProjectRSSFeed=codeplex%3a%2f%2fsourcecontrol%2fsqlservercache")
    End Sub

    ''' <summary>
    ''' Pointer to menu option to shell the RSS feed for all releases
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub ToolStripButton6_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton6.Click
        Call AllReleasesToolStripMenuItem_Click(Nothing, Nothing)
    End Sub

    ''' <summary>
    ''' Shells out to the system and starts a url or program.
    ''' </summary>
    ''' <param name="Url"></param>
    ''' <remarks></remarks>
    Sub StartUrl(ByVal Url As String)

        Dim Process As System.Diagnostics.Process

        Try
            Process = New System.Diagnostics.Process()
            Process.StartInfo.FileName = Url
            Process.StartInfo.WindowStyle = ProcessWindowStyle.Normal
            Process.Start()
        Catch ex As Exception
            MessageBox.Show(ex.Message, "An error has occured", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

    End Sub

    ''' <summary>
    ''' Save text from the text editor tab
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub ToolStripButton7_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton7.Click
        SaveFileDialog1.OverwritePrompt = True
        SaveFileDialog1.SupportMultiDottedExtensions = True
        SaveFileDialog1.Title = "Save Text"
        SaveFileDialog1.FileName = ""
        SaveFileDialog1.ShowDialog()

        If SaveFileDialog1.FileName.Replace(" ", "") = "" Then
            Exit Sub
        Else
            Try
                My.Computer.FileSystem.WriteAllText(SaveFileDialog1.FileName, txtEditor.Text, False, System.Text.Encoding.ASCII)
            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
        End If
    End Sub

    ''' <summary>
    ''' Clipboard, copy text for the SQL text box
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub ToolStripButton8_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton8.Click
        If txtEditor.SelectedText IsNot Nothing Then
            Try
                Clipboard.SetText(txtEditor.SelectedText, TextDataFormat.Text)
            Catch

            End Try
        End If

    End Sub

    ''' <summary>
    ''' Clipboard, cut text for the SQL text box
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub ToolStripButton9_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton9.Click
        If txtEditor.SelectedText IsNot Nothing Then
            Try
                Clipboard.SetText(txtEditor.SelectedText, TextDataFormat.Text)
                txtEditor.SelectedText = ""
            Catch
                ' Eat error
            End Try
        End If

    End Sub

    ''' <summary>
    ''' Delete text from the SQL text box
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub ToolStripButton10_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton10.Click
        Try
            txtEditor.SelectedText = ""
        Catch
            ' Eat error
        End Try
    End Sub

    ''' <summary>
    ''' Select all text in the SQL text box
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub ToolStripButton11_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton11.Click
        txtEditor.Focus()
        txtEditor.SelectAll()
    End Sub

End Class
